// ContactTreeView.cs created with MonoDevelop
// User: draek at 10:05 A 20/11/2007
//
// To change standard headers go to Edit->Preferences->Coding->Standard Headers
//

using System;
using System.Collections.Generic;

using Gtk;
using Gdk;
using Pango;

using Galaxium.Core;
using Galaxium.Gui;
using Galaxium.Gui.GtkGui;

namespace Galaxium.Protocol.Aim.GtkGui
{
	public sealed class ContactTreeView : GtkTreeView<HintTreeNodeRenderer>
	{
		uint _tooltipTimeout;
		ContactListTooltip _currentTooltip;
		Gdk.Rectangle _tooltipRectangle;
		
		internal ContactTreeView () : base ()
		{
			AddNodeBuilder (new ContactTreeNodeBuilder ());
			AddNodeBuilder (new GroupTreeNodeBuilder ());
			
			this.RulesHint = false;
			this.Reorderable = false;
			
			TreeViewColumn expander = new TreeViewColumn ();
			expander.PackStart (new ExpanderCellRenderer (), true);
			expander.MaxWidth = 16;
			InsertColumn (expander, 0);
			ExpanderColumn = expander;
			
			Filter = new ContactTreeFilter();
		}
		
		private void RulesHintDataFunc (CellLayout layout, CellRenderer cell, TreeModel model, TreeIter iter)
		{
			TreeNodeRenderer.RenderBackground (cell);
		}
		
		protected override void InitializeLayout ()
		{
			TreeViewColumn col = new TreeViewColumn ();

			CellRendererText textRenderer = new ContactCellRendererText (AimProtocol.Instance);
			CellRendererPixbuf pixbufRenderer = new CellRendererPixbuf ();

			col.PackStart (pixbufRenderer, false);
			col.PackStart (textRenderer, true);

			col.SetCellDataFunc (textRenderer, new CellLayoutDataFunc (TextDataFunc));
			col.SetCellDataFunc (pixbufRenderer, new CellLayoutDataFunc (PixbufDataFunc));

			this.AppendColumn(col);

			ApplyLayout (col, textRenderer, pixbufRenderer);
		}

		protected override void ApplyLayout (TreeViewColumn col, CellRendererText textRenderer, CellRendererPixbuf pixbufRenderer)
		{
			textRenderer.Ellipsize = EllipsizeMode.End;
			textRenderer.Xalign = 0.0f;
			textRenderer.Xpad = 0;
			
			col.Expand = true;
			col.MinWidth = 25;
		}

		protected override ITreeNodeRenderer GetTreeNodeRenderer ()
		{
			return new HintTreeNodeRenderer (this);
		}
		
		protected override bool OnLeaveNotifyEvent(Gdk.EventCrossing oEvent)
		{
			DestroyTooltip();
			return base.OnLeaveNotifyEvent(oEvent);
		}
		
		protected override bool OnMotionNotifyEvent (Gdk.EventMotion oEvent)
		{
			TreePath oPath;
			int iX = (int)oEvent.X;
			int iY = (int)oEvent.Y;
			
			if (_tooltipTimeout != 0)
			{
				if ((iY > _tooltipRectangle.Y) && ((iY - _tooltipRectangle.Height) < _tooltipRectangle.Y))
					return base.OnMotionNotifyEvent(oEvent);
					
				DestroyTooltip();
			}
			
			if (!GetPathAtPos(iX, iY, out oPath))
				return base.OnMotionNotifyEvent(oEvent);
			
			_tooltipRectangle = GetCellArea(oPath, null);
			
			uint node;
			AimContact contact;
			
			this.GetNodeFromPath(oPath, out node);
			contact = this.GetNodeObject(node) as AimContact;

			if (contact == null)
				return base.OnMotionNotifyEvent(oEvent);

			_tooltipTimeout = GLib.Timeout.Add(1500, delegate { ShowTooltip(contact); return false; });
			return false;
		}
		
		private void ShowTooltip(AimContact contact)
		{
			_currentTooltip = new ContactListTooltip(contact);
			
			Gdk.Rectangle oRectangle;
			int iOriginX, iOriginY;
			
			GdkWindow.GetOrigin(out iOriginX, out iOriginY);
			
			oRectangle = new Gdk.Rectangle();
			oRectangle.X = iOriginX + _tooltipRectangle.X;
			oRectangle.Y = iOriginY + _tooltipRectangle.Y;
			oRectangle.Width = _tooltipRectangle.Width;
			oRectangle.Height = _tooltipRectangle.Height;
			
			_currentTooltip.PositionToRectangle(oRectangle, Screen);
			_currentTooltip.ShowAll();
		}
		
		void DestroyTooltip()
		{
			if(_currentTooltip != null)
			{
				_currentTooltip.Destroy();
				_currentTooltip = null;
			}
			
			if (_tooltipTimeout > 0)
				GLib.Source.Remove(_tooltipTimeout);
		}
	}
}